package connections;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;

public class Connection implements ConnectionListener, Runnable {

	InputStream is;

	OutputStream os;

	ConnectionListener mainProgram;

	int waitForBytes;

	char terminationChar = 0;

	char startChar = 0;

	String address ;

	//String filename;

	boolean listening = false;

	public Connection() {
		mainProgram = this;
	}

	public void disconnect(){
		
		try {
			if (is != null) is.close();
			if (os != null) os.close();

			listening =false;
		} catch (IOException e) {
			System.out.println("Never Opened");
		}
	}
	void start(){
		Thread myThread = new Thread(this);
		myThread.start();
		
	}

	//public void setFilename(String _s) {
	//	filename = _s;
	//}

	//public String getFilename() {
	//	return filename;
	//}

	public String getAddress() {
		return address;
	}
	public void setAddress(String _a) {
		address = _a;
	}
	public int getBacklog() {
		int a = -1;
		try {
			a = is.available();
		} catch (IOException e) {
			mainProgram.feedback(this, "available" + e);
		}
		return a;
	}

	public InputStream getInputStream() {
		return is;
	}

	public OutputStream getOutputStream() {
		return os;
	}

	public void send(byte _b) {
	
		try {
			os.write(_b);
			os.flush();
		}catch (NullPointerException e) {
			mainProgram.feedback(this, "can't send, connection already dead");
		} catch (IOException e) {
			mainProgram.feedback(this, "prob" + e);
		}
	}

	public void send(byte[] _b) {
		try {
			os.write(_b);
			os.flush();
		} catch (IOException e) {
			mainProgram.feedback(this, "prob" + e);
		}
	}

	public void send(byte[] _b, String _filename) {
		try {

			DataOutputStream dos = new DataOutputStream(os);
			dos.writeUTF(_filename);
			os.write(_b);
			os.flush();
		} catch (IOException e) {
			mainProgram.feedback(this, "prob" + e);
		}
	}

	public void send(byte[] _b, String _filename, int _len) {
		try {

			DataOutputStream dos = new DataOutputStream(os);
			dos.writeUTF(_filename);
			os.write(_b, 0, _len);
			os.flush();
		} catch (IOException e) {
			mainProgram.feedback(this, "prob" + e);
		}
	}

	public void send(byte[] _b, int _offset, int _len) {
		try {
			os.write(_b, _offset, _len);
			os.flush();
		} catch (IOException e) {
			mainProgram.feedback(this, "prob" + e);
		}
	}

	public void addListener(ConnectionListener _cl) {
		mainProgram = _cl;
		waitForBytes = -1;
		terminationChar = 0;
		startChar = 0;

		if (listening == false) start();
	

	}

	public void addListener(ConnectionListener _cl, int _waitForBytes) {
		mainProgram = _cl;
		waitForBytes = _waitForBytes;
		terminationChar = 0;
		startChar = 0;
		if (listening == false) start();
	}

	public void addListener(ConnectionListener _cl, char _terminationChar) {
		mainProgram = _cl;
		terminationChar = _terminationChar;
		waitForBytes = 0;
		startChar = 0;
		if (listening == false) start();
	}

	public void addListener(ConnectionListener _cl, char _startChar, int _waitForBytes) {
		mainProgram = _cl;
		startChar = _startChar;
		terminationChar = 0;
		waitForBytes = _waitForBytes;
		if (listening == false) start();
	}

	public void clearInput() {
		try {
			if (is.available() > 0) {
				byte[] garbage = new byte[is.available()];
				is.read(garbage);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void run() {
		String accumulatedString = "";

		listening = true;

		while (listening) {
			//try {
			//	Thread.sleep(20);
			//} catch (InterruptedException e) {
			//	mainProgram.feedback(this, "can't sleep" + e);
			//}
	
			if (is == null) { // this lets them add a listener before the connection is made
				try {
					Thread.sleep(300);
				} catch (InterruptedException e) {
					mainProgram.feedback(this, "can't sleep" + e);
				}
			} else {
				try {
					if (startChar != 0) {
						char newChar = (char) is.read();
						if (newChar == -1) break;
						if (newChar == startChar) {
							byte[] input = new byte[waitForBytes];
							input[0] = (byte) newChar;
							
							is.read(input, 1, waitForBytes - 1);
							mainProgram.incoming(this, input);
						}
					} else if (waitForBytes == -1) {

						int available = is.available();
						if (available > 0) {

							byte[] input = new byte[available];
							int back = is.read(input);
							if (back == -1) break;
							mainProgram.incoming(this, input);
						}
					} else if (waitForBytes == 0) { // look for termination car
						char newChar = (char) is.read();
						if (newChar == -1) break;
						if (newChar == terminationChar) {
							accumulatedString = accumulatedString + newChar;
							mainProgram.incoming(this, (accumulatedString).getBytes());
							// because this is threaded? accumulated string gets erased before processed
							accumulatedString = "";
						} else {
							accumulatedString = accumulatedString + newChar;
						}

					} else { // wait for a specific number of chars.
						byte[] input = new byte[waitForBytes];
						int back = is.read(input);
						if (back == -1) break;
						mainProgram.incoming(this, input);
						// mainProgram.inputFromBlueTooth(this, "L".getBytes());
					}

				} catch (IOException e) {
					listening = false;
					mainProgram.feedback(this, "Stopped Listening" );
				}
			}
		}

	}

	public void incoming(Connection _c, byte[] _input) {
		// TODO Auto-generated method stub

	}

	public void feedback(Connection _c, String _feedback) {
		// TODO Auto-generated method stub

	}

	public void connectionMade(Connection _c, String _address) {
		// TODO Auto-generated method stub
		setAddress(_address);
	}
	public static String[] split(String input, char delim) {

		String textsofar = "";
		Vector rVector = new Vector();
		for (int i = 0; i < input.length(); i++) {
			char c = input.charAt(i);
			if (c == delim) {
				rVector.addElement(textsofar);
				textsofar = "";
			} else {
				textsofar = textsofar + (char) c;
			}
		}
		rVector.addElement(textsofar);
		String[] stringArray = new String[rVector.size()];
		rVector.copyInto(stringArray);
		return stringArray;
	}
	public boolean isListening(){
		return listening;
	}


}
